from datetime import datetime
from zoneinfo import ZoneInfo

from django.contrib import admin, messages
from django.utils.translation import gettext_lazy, gettext
from django.contrib.admin import helpers
from django.core.exceptions import ValidationError

from utils.model import NoDeleteSelectModelAdmin, BaseModelAdmin
from apps.app_users.email_sender import EmailSender
from apps.app_tx_meeting.managers import tx_meeting_configs
from apps.app_tx_meeting.models import (
    TxMeetingConfig,
    MeetingRoom,
    MeetingReservation,
    MeetingReservationLog,
    ReservationNoShow,
    NoShowWhitelist,
)
from apps.app_tx_meeting.models import MeetingUser
from apps.app_tx_meeting.tx_clients import inputs
from apps.app_tx_meeting import builders
from apps.app_tx_meeting.forms import TxMeetingConfigForm


TZ_SHANGHAI = ZoneInfo('Asia/Shanghai')


@admin.register(TxMeetingConfig)
class TxMeetingConfigAdmin(NoDeleteSelectModelAdmin):
    form = TxMeetingConfigForm
    list_display = ['id', 'name', 'value', 'creation_time', 'update_time', 'remark']
    list_display_links = ['id', 'name']
    actions = ('update_configs', 'check_tx_app_configs', 'check_tx_email_configs')
    show_full_result_count = False

    @admin.action(description=gettext_lazy('清理更新配置项'))
    def update_configs(self, request, queryset):
        tx_meeting_configs.get_configs_no_cache(remove_invalid=True)

    update_configs.act_not_need_selected = True

    @admin.action(description=gettext_lazy('校验腾讯会议应用配置信息'))
    def check_tx_app_configs(self, request, queryset):
        tx_meeting_configs.get_configs_no_cache(remove_invalid=False)
        tx_client = builders.build_tx_meeting_client()
        r = tx_client.list_corp_meetings(
            params=inputs.ListMeetingsInput(
                meeting_state=3
            ))
        if r.ok:
            self.message_user(request=request, message=gettext('测试请求腾讯会议服务接口成功'), level=messages.SUCCESS)
        else:
            self.message_user(request=request, message=gettext('测试请求腾讯会议服务接口失败。') + str(r.error), level=messages.ERROR)

    check_tx_app_configs.act_not_need_selected = True

    @admin.action(description=gettext_lazy('校验邮件配置信息'))
    def check_tx_email_configs(self, request, queryset):
        tx_meeting_configs.get_configs_no_cache(remove_invalid=False)
        use_ssl = tx_meeting_configs.get(tx_meeting_configs.ConfigName.EMAIL_USE_SSL.value)
        use_tls = tx_meeting_configs.get(tx_meeting_configs.ConfigName.EMAIL_USE_TLS.value)
        use_ssl = True if use_ssl == 'true' else False
        use_tls = True if use_tls == 'true' else False

        if use_tls and use_ssl:
            self.message_user(
                request=request, message=gettext('邮件配置信息有误，TLS和SSL加密只能有一个为"true"'), level=messages.ERROR)
            return

        try:
            email_host_user = tx_meeting_configs.get(tx_meeting_configs.ConfigName.EMAIL_HOST_USER.value)
            conn = EmailSender.get_connection(
                host=tx_meeting_configs.get(tx_meeting_configs.ConfigName.EMAIL_HOST.value),
                port=int(tx_meeting_configs.get(tx_meeting_configs.ConfigName.EMAIL_PORT.value)),
                username=email_host_user,
                password=tx_meeting_configs.get(tx_meeting_configs.ConfigName.EMAIL_HOST_PASSWORD.value),
                use_ssl=use_ssl, use_tls=use_tls,
            )
            num = EmailSender.send_mail(
                connection=conn, from_email=email_host_user, receivers=[request.user.username],
                subject='Send Email Test', message=gettext('这是一封测试邮件，测试腾讯会议预定服务邮件配置参数是否正常。')
            )
            if num >= 1:
                self.message_user(
                    request=request, message=gettext('邮件参数配置正常，已发送测试邮件。'), level=messages.SUCCESS)
            else:
                self.message_user(
                    request=request, message=gettext('邮件参数配置有误，发送测试邮件失败。'), level=messages.ERROR)
        except Exception as exc:
            self.message_user(
                    request=request, message=gettext('邮件参数配置有误，发送测试邮件错误。') + str(exc),level=messages.ERROR)

    check_tx_email_configs.act_not_need_selected = True

    def changelist_view(self, request, extra_context=None):
        if request.method == "POST":
            action = self.get_actions(request)[request.POST['action']][0]
            act_not_need_selected = getattr(action, 'act_not_need_selected', False)
            if act_not_need_selected:
                post = request.POST.copy()
                post.setlist(helpers.ACTION_CHECKBOX_NAME, [0])
                request.POST = post

        return super().changelist_view(request, extra_context)

    def get_changelist_instance(self, request):
        cl = super().get_changelist_instance(request)
        cl.show_admin_actions = True
        return cl

    def save_model(self, request, obj, form, change):
        super().save_model(request=request, obj=obj, form=form, change=change)
        tx_meeting_configs.clear_cache()


@admin.register(MeetingRoom)
class MeetingRoomAdmin(NoDeleteSelectModelAdmin):
    list_display = [
        'id', 'type_50_num', 'type_50_visible', 'type_100_num', 'type_100_visible',
        'type_300_num', 'type_300_visible', 'type_500_num', 'type_500_visible',
        'type_1000_num', 'type_1000_visible', 'creation_time', 'update_time'
    ]
    list_display_links = ['id',]
    fieldsets = (
        (gettext_lazy('50方'), {'fields': ('type_50_num', 'type_50_visible')}),
        (gettext_lazy('100方'), {'fields': ('type_100_num', 'type_100_visible')}),
        (gettext_lazy('300方'), {'fields': ('type_300_num', 'type_300_visible')}),
        (gettext_lazy('500方'), {'fields': ('type_500_num', 'type_500_visible')}),
        (gettext_lazy('1000方'), {'fields': ('type_1000_num', 'type_1000_visible')}),
    )

    def save_model(self, request, obj, form, change):
        if not change:
            main_obj = MeetingRoom.objects.filter(id=MeetingRoom.MAIN_ID).first()
            if main_obj:
                self.message_user(request=request, message=gettext('不允许添加新纪录，只能有一条虚拟会议室资源配置记录'), level=messages.WARNING)
                raise ValidationError(gettext('不允许添加新纪录，只能有一条虚拟会议室资源配置记录'))

            obj.id = MeetingRoom.MAIN_ID

        super().save_model(request=request, obj=obj, form=form, change=change)


@admin.register(MeetingUser)
class MeetingUserAdmin(BaseModelAdmin):
    list_display = [
        'id', 'user', 'role', 'status', 'creation_time', 'update_time'
    ]
    list_display_links = ['id',]
    list_select_related = ('user',)
    list_filter = ['role', 'status']
    raw_id_fields = ('user',)


@admin.register(MeetingReservation)
class MeetingReservationAdmin(NoDeleteSelectModelAdmin):
    list_display = [
        'id', 'subject', 'start_time', 'show_start_time', 'end_time', 'show_end_time',
        'people_num', 'room_type', 'status', 'user',
        'tx_meeting_id', 'tx_meeting_code', 'tx_meeting_userid', 'tx_user_nick_name',
        'tx_start_time', 'tx_end_time', 'tx_join_url',
        'room_reserve_start', 'show_room_reserve_start', 'room_reserve_end', 'show_room_reserve_end',
        'room_reserve_status', 'room_reserve_desc',
        'advance_notice_seconds', 'need_notice_time', 'email_notice_id',
        'creation_time', 'update_time'
    ]
    list_display_links = ['id',]
    list_filter = ['room_type', 'status']
    list_select_related = ('user',)
    search_fields = ('subject', 'tx_meeting_userid', 'tx_meeting_code', 'user__username')
    raw_id_fields = ('user',)

    @admin.display(description=gettext_lazy('预定开始时间'))
    def show_start_time(self, obj):
        return self.ts_to_datetime_str(obj.start_time)

    @admin.display(description=gettext_lazy('预定结束时间'))
    def show_end_time(self, obj):
        return self.ts_to_datetime_str(obj.end_time)

    @admin.display(description=gettext_lazy('会议室预留开始时间'))
    def show_room_reserve_start(self, obj):
        return self.ts_to_datetime_str(obj.room_reserve_start)

    @admin.display(description=gettext_lazy('会议室预留结束时间'))
    def show_room_reserve_end(self, obj):
        return self.ts_to_datetime_str(obj.room_reserve_end)

    @staticmethod
    def ts_to_datetime_str(ts: int) -> str:
        return datetime.fromtimestamp(ts, tz=TZ_SHANGHAI).isoformat(sep=' ', timespec='seconds')


@admin.register(MeetingReservationLog)
class MeetingReservationLogAdmin(NoDeleteSelectModelAdmin):
    list_display = [
        'id', 'log_type', 'operate_status', 'operator', 'creation_time', 'reservation_id', 'content'
    ]
    list_display_links = ['id',]
    list_filter = ['log_type', 'operate_status']
    search_fields = ('reservation_id', 'operator')


@admin.register(ReservationNoShow)
class ReservationNoShowAdmin(BaseModelAdmin):
    list_display = [
        'id', 'username', 'user_nickname', 'creation_time', 'valid_status', 'reservation',
        'reservation_id', 'remarks', 'email_notice_id'
    ]
    list_display_links = ['id',]
    list_filter = ['valid_status',]
    list_select_related = ('reservation',)
    search_fields = ('username', 'reservation__id')
    raw_id_fields = ('reservation', 'email_notice')


@admin.register(NoShowWhitelist)
class NoShowWhitelistAdmin(BaseModelAdmin):
    list_display = [
        'id', 'username', 'user_nickname', 'creation_time', 'update_time', 'creator', 'remarks'
    ]
    list_display_links = ['id',]
    search_fields = ('username', 'user_nickname', 'remarks')
